﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iLangl.Model;
using iLangl.LanguageWire.DAL.iLanglDAL;
using iLangl.LanguageWire.Actions;
using iLangl.LanguageWire.DAL.LanguageWireDAL;
using System.Collections;

namespace iLangl.LanguageWire.Managers
{
	public class SynchronizationManager : BaseManager
	{
		#region Singelton Pattern
		private SynchronizationManager()
		{
		}

		private static SynchronizationManager instance;
		private static object mutex = new object();
		/// <summary>
		/// The instance of the SynchronizationManager.
		/// </summary>
		public static SynchronizationManager Instance
		{
			get
			{
				if (instance == null)
				{
					lock (mutex)
					{
						if (instance == null)
						{
							instance = new SynchronizationManager();
						}
					}
				}
				return instance;
			}
		}
		#endregion


		public SyncedOneWayData GetSyncedData()
		{
			return DALFacade.Instance.SynchronizedDAL.SyncObjects();

		}

		public void Synchronize()
		{
			SyncedOneWayData data = GetSyncedData();

			if (!data.IsDataPresent())
				return;

			SyncedDataAction syncedDataAction = new SyncedDataAction(data);
			syncedDataAction.Send();

			DALFacade.Instance.SynchronizedDAL.MarkAsSynced(data);

		}


		public void SyncData(SyncedOneWayData result)
		{

			if ((result.Companies != null) && (result.Companies.Length > 0))
			{
				foreach (Company company in result.Companies)
				{
					CompanyManager.Instance.UpdateCompany(company);
				}
			}

			if ((result.Projects != null) && (result.Projects.Length > 0))
			{

				foreach (Project project in result.Projects)
				{
					ProjectManager.Instance.UpdateProject(new ProjectLW(project));
				}
			}

			DALFacade.Instance.SynchronizedDAL.MarkAsSynced(result);
		}

		public void RegisterProjectToSync(ProjectLW project)
		{

			if (project == null)
				return;

			foreach (Translation translation in project.Instance.Translations)
			{
				JobInfo ji = DALFacadeLW.Instance.ProjectDAL.GetJobInfo(int.Parse(translation.TPIdentity));

				DALFacadeLW.Instance.SynchronizationDAL.InsertJobToSync(ji.JobId);

				if (ji.Jobs != null)
				{
					foreach (Int32 jobid in ji.Jobs)
					{
						DALFacadeLW.Instance.SynchronizationDAL.InsertJobToSync(jobid);
					}
				}
			}
		}

		public void RemoveProjectFromSync(ProjectLW project)
		{
			if (project == null)
				return;

			foreach (Translation translation in project.Instance.Translations)
			{
				JobInfo ji = DALFacadeLW.Instance.ProjectDAL.GetJobInfo(int.Parse(translation.TPIdentity));

				DALFacadeLW.Instance.SynchronizationDAL.RemoveJobFromSync(ji.JobId);
				foreach (Int32 jobid in ji.Jobs)
				{
					DALFacadeLW.Instance.SynchronizationDAL.RemoveJobFromSync(jobid);
				}
			}
		}

		public void Analyze()
		{
			SyncedDataLW syncedData = DALFacadeLW.Instance.SynchronizationDAL.GetJobsToSync();

			Hashtable jobs = new Hashtable();

			//Read changed Jobs and parents
			foreach (Int32 jobId in syncedData.JobsToSync)
			{
				JobInfo ji = DALFacadeLW.Instance.ProjectDAL.GetJobInfo(jobId);

				jobs[ji.JobId] = ji;

				if (ji.ParentJobId > 0)
				{
					if (jobs[ji.ParentJobId] == null)
					{
						JobInfo parentji = DALFacadeLW.Instance.ProjectDAL.GetJobInfo(ji.ParentJobId);
						ji.ParentJobInfo = parentji;
						jobs[parentji.JobId] = parentji;
						parentji.AddChildren(ji);
					}
				}
			}

			//Read childs information for parents
			foreach (JobInfo ji in jobs.Values)
			{
				foreach (Int32 childJobId in ji.Jobs)
				{
					JobInfo childji = DALFacadeLW.Instance.ProjectDAL.GetJobInfo(childJobId);
					ji.ParentJobInfo = ji;
					jobs[childji.JobId] = childji;
					ji.AddChildren(childji);
				}
			}

			Hashtable projectstorecalculate = new Hashtable();

			foreach (JobInfo ji in jobs.Values)
			{
				if (ji.IsParent())
				{
					Translation translation = DALFacade.Instance.TranslationDAL.ReadTranslationByTPIdentity(ji.JobId.ToString());
					TranslationStatuses.eTranslationStatus status = TranslationStatuses.GetStatus(translation.Status);
					TranslationStatuses.eTranslationStatus lwstatus = MappingManager.Instance.GetTranslationStatus(ji.Status);


					ji.Translation = translation;

					//Status Change Analize
					if (status != lwstatus)
					{
						projectstorecalculate[translation.Project.Id] = translation;


						translation.Status = TranslationStatuses.GetStatus(lwstatus);
						if ((status == TranslationStatuses.eTranslationStatus.InProgress) &&
								(lwstatus == TranslationStatuses.eTranslationStatus.Finished))
						{
							ContentManager.Instance.DownloadContent(translation, status, lwstatus);
						}
					}

					//PM changes
					if (translation.Responsible == null)
					{
						translation.Responsible = DALFacade.Instance.ContactDAL.ReadContactByTPIdentity(ji.ResponsiblePerson.ToString());
					}

					if (translation.Responsible.TPIdentity != ji.ResponsiblePerson.ToString())
					{
						//Update Contact
						translation.Responsible = ContactManager.Instance.GetResponsiblePerson(ji.JobId);
					}

				}
			}

			//Progress Recalculation
			List<JobInfo> jis = new List<JobInfo>();

			foreach (JobInfo ji in jobs.Values)
			{
				jis.Add(ji);
			}

			ProgressManager.Instance.RecalculateProgress(jis);

			//Update Translations
			foreach (JobInfo ji in jis)
			{
				DALFacade.Instance.TranslationDAL.UpdateTranslation(ji.Translation, null);
			}

			//Status Recalculation for Projects
			foreach (String projectId in projectstorecalculate.Keys)
			{
				ProjectManager.Instance.UpdateProjectStatus(projectId);
			}

			//Mark jobs like synced
			DALFacadeLW.Instance.SynchronizationDAL.MarkJobsAsSynced(syncedData);
		}

		
	}
}
